package io.grpc.examples.helloworldtls;

import java.io.File;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.net.ssl.SSLException;

import com.asgard.crypto.CryptoService;
import com.asgard.crypto.ECKey;
import com.asgard.keybox.KeyBox;

import io.grpc.ManagedChannel;
import io.grpc.StatusRuntimeException;
import io.grpc.examples.helloworld.GreeterGrpc;
import io.grpc.examples.helloworld.HelloReply;
import io.grpc.examples.helloworld.HelloRequest;
import io.grpc.examples.helloworldtls.trust.MyTrustManagerFactory;
import io.grpc.netty.GrpcSslContexts;
import io.grpc.netty.NegotiationType;
import io.grpc.netty.NettyChannelBuilder;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;

public class NSMHelloWorldClientTls {
	private static final Logger logger = Logger.getLogger(NSMHelloWorldClientTls.class.getName());

	public static void main(String[] args) throws Exception {
		CryptoService.setUseSM(false);
		String keyboxPath = "E:\\develop\\workspace\\eclipse\\asgard\\grpc-tls-test\\src\\main\\resources\\NotSM\\resources\\pbftvp02\\keybox.xml";

        // CryptoService.setUseSM(true);
        // String keyboxPath = "E:\\develop\\tomcat\\apache-tomcat-8.5.54-8203\\resources\\SMTrueSSL\\keybox.xml";

		BCHelloWorldClientTls client = new BCHelloWorldClientTls("localhost", 7402, buildSslContext(keyboxPath));
		String user = "world taifu";
		client.greet(user);
		client.shutdown();
	}

	private final ManagedChannel channel;
	private final GreeterGrpc.GreeterBlockingStub blockingStub;

	static SslContext buildSslContext(String keyboxPath) throws Exception {
		File keyBoxFile = new File(keyboxPath);
		KeyBox keyBox = new KeyBox();
		keyBox.loadFromFile(keyBoxFile, "PASSWORD");
		ECKey eckey = keyBox.getKey("ECKey");
		PrivateKey privateKey = eckey.getPrivateKey();
		X509Certificate x509Certificate = keyBox.getCertificate("ENROLL_CERT").getX509Cert();
//        System.out.println("x509Certificate:"+x509Certificate.toString());
		SslContextBuilder builder = GrpcSslContexts.forClient().trustManager(new MyTrustManagerFactory(""))
				.keyManager(privateKey, x509Certificate);
		return builder.build();
	}

	public NSMHelloWorldClientTls(String host, int port, SslContext sslContext) throws SSLException {

		this(NettyChannelBuilder.forAddress(host, port).negotiationType(NegotiationType.TLS).sslContext(sslContext)
				.build());
	}

	NSMHelloWorldClientTls(ManagedChannel channel) {
		this.channel = channel;
		blockingStub = GreeterGrpc.newBlockingStub(channel);
	}

	public void shutdown() throws InterruptedException {
		channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
	}

	public void greet(String name) {
		logger.info("Will try to greet " + name + " ...");
		HelloRequest request = HelloRequest.newBuilder().setName(name).build();
		HelloReply response;
		try {
			response = blockingStub.sayHello(request);
		} catch (StatusRuntimeException e) {
			logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
			return;
		}
		logger.info("============get grpc msg==============");
		System.out.println("Greeting: " + response.getMessage());
		logger.info("============get grpc msg==============");
	}
}